package com.usefullc.crawler.service;
import com.google.common.collect.Lists;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jayway.jsonpath.JsonPath;
import com.usefullc.common.enums.YesNoEnum;
import com.usefullc.common.exception.BizException;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.common.util.JsonUtil;
import com.usefullc.common.util.http.HttpNewUtils;
import com.usefullc.common.util.http.RequestRes;
import com.usefullc.common.util.http.ResponseRes;
import com.usefullc.crawler.constants.CrawlerCacheConstants;
import com.usefullc.crawler.constants.CrawlerConstants;
import com.usefullc.crawler.domain.*;
import com.usefullc.crawler.enums.ActiveInstanceStatusEnum;
import com.usefullc.crawler.enums.ProcessStatusEnum;
import com.usefullc.crawler.enums.SampleTypeEnum;
import com.usefullc.crawler.enums.TemplateStatusEnum;
import com.usefullc.crawler.mapper.ActiveProcessMapper;
import com.usefullc.crawler.query.ActiveInstanceQuery;
import com.usefullc.crawler.query.ActiveMainInstanceQuery;
import com.usefullc.crawler.query.ActiveProcessQuery;
import com.usefullc.crawler.query.ActiveQuery;
import com.usefullc.crawler.task.TaskMessageQueue;
import com.usefullc.crawler.utils.ExtractUrlUtils;
import com.usefullc.crawler.vo.ActiveProcessVo;
import com.usefullc.crawler.vo.ClientActiveProcessTaskVo;
import com.usefullc.crawler.vo.ClientResultVo;
import com.usefullc.crawler.vo.TaskTypeVo;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.service.AbstractBizService;
import com.usefullc.system.service.DataConfigService;
import net.minidev.json.JSONArray;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.concurrent.atomic.AtomicBoolean;

/**
 * 爬虫活动流程服务类
 *
 * @author: 星空
 * @date: 2022-12-14
 */
@Service
public class ActiveProcessService extends AbstractBizService<ActiveProcessMapper, ActiveProcess, ActiveProcessQuery> {

    @Autowired
    private TemplateService templateService;

    @Autowired
    private ActiveService activeService;

    @Autowired
    private ActiveInstanceService activeInstanceService;

    @Autowired
    private ActiveMainInstanceService activeMainInstanceService;


    @Autowired
    private TaskMessageQueue taskMessageQueue;

    @Autowired
    private DataConfigService dataConfigService;


    @Autowired
    private RedisTemplate redisTemplate;

    @Value("${usefullc.cralwer.model}")
    private String crawlerModel;

//    @Value("${usefullc.cralwer.client_collect_url}")
//    private String crawlerUrl;

//    private String INPUT;
//
//    {
//        for (int i = 0; i < 100; i++) {
//            INPUT += i;
//        }
//    }


    /**
     * 全局拦截开关
     */
    private AtomicBoolean atoIntercept = new AtomicBoolean(false);

    @Override
    protected QueryWrapper<ActiveProcess> getQueryWrapper(ActiveProcessQuery query) {
        QueryWrapper<ActiveProcess> queryWrapper = super.getQueryWrapper(query);
        return queryWrapper;
    }

    public Pager<ActiveProcessVo> findVoByPage(ActiveProcessQuery query) {
        Pager<ActiveProcess> page = this.findByPage(query);
        Pager<ActiveProcessVo> newPage = new Pager<>(page);
        List<ActiveProcess> dataList = page.getDataList();
        List<ActiveProcessVo> newDataList = new ArrayList<>();
        newPage.setDataList(newDataList);
        for (ActiveProcess activeProcess : dataList) {
            ActiveProcessVo activeProcessVo = BeanUtils.beanCopy(activeProcess, ActiveProcessVo.class);
            newDataList.add(activeProcessVo);
        }
        return newPage;
    }

    private List<String> analyseUrl(String url, Long activeProcessId, Long prevActiveId, Map<String, String> variableMap) {
        String[] urls = url.split("\n|,");
        List<String> resultUrls = new ArrayList<>();
//        reqUrls.addAll(Arrays.asList(urls));
        for (String thisUrl : urls) {
            if (StringUtils.isEmpty(thisUrl)) {
                continue;
            }
            resultUrls = analyseResUrl(thisUrl, activeProcessId, prevActiveId,null);
            resultUrls = analyseMultiVariableUrl(resultUrls, variableMap);
            resultUrls = analyseVariableUrl(resultUrls, variableMap);
            resultUrls = analyseRangeVariableUrl(resultUrls);
        }
        return resultUrls;
    }


    public List<String> analyseUrl(String url, Long activeProcessId, Long prevActiveId, Map<String, String> variableMap,List<ActiveInstance> prevActiveInstanceList) {
        String[] urls = url.split("\n|,");
        List<String> resultUrls = new ArrayList<>();
//        reqUrls.addAll(Arrays.asList(urls));
        for (String thisUrl : urls) {
            if (StringUtils.isEmpty(thisUrl)) {
                continue;
            }
            resultUrls = analyseResUrl(thisUrl, activeProcessId, prevActiveId,prevActiveInstanceList);
            resultUrls = analyseMultiVariableUrl(resultUrls, variableMap);
            resultUrls = analyseVariableUrl(resultUrls, variableMap);
            resultUrls = analyseRangeVariableUrl(resultUrls);
        }
        return resultUrls;
    }

    private List<String> analyseResUrl(String url, Long activeProcessId, Long prevActiveId,List<ActiveInstance> prevActiveInstanceList) {
        List<String> reqUrls = new ArrayList<>();
        if (url.startsWith("$." + CrawlerConstants.ACTIVE_PREV_RESULT)) {
            url = StringUtils.remove(url, CrawlerConstants.ACTIVE_PREV_RESULT);
            //获取前一活动实例所有的解析结果
            if(CollectionUtils.isEmpty(prevActiveInstanceList)){
                ActiveInstanceQuery activeInstancePrevQuery = new ActiveInstanceQuery();
                activeInstancePrevQuery.setActiveId(prevActiveId);
                activeInstancePrevQuery.setActiveProcessId(activeProcessId);
                activeInstancePrevQuery.setStatus(YesNoEnum.YES.getCode());
                prevActiveInstanceList = activeInstanceService.findAll(activeInstancePrevQuery);
            }
            for (ActiveInstance activeInstance : prevActiveInstanceList) {
                if(activeInstance.getStatus() == YesNoEnum.NO.getCode()){
                    continue;
                }
                String responseAnalyseBody = activeInstance.getResponseAnalyseBody();
                List<Object> analyseUrls = JsonPath.read(responseAnalyseBody, url);
                List<String> analyseRawUrls = new ArrayList<>();
                for (Object analyseUrl : analyseUrls) {
                    if (analyseUrl instanceof JSONArray) {
                        ((JSONArray) analyseUrl).forEach(data -> {
                            analyseRawUrls.add(data.toString());
                        });
                    } else {
                        analyseRawUrls.add(analyseUrl.toString());
                    }
                }

                for (String analyseUrl : analyseRawUrls) {
                    if (analyseUrl.startsWith("$." + CrawlerConstants.ACTIVE_CURRENT_URL)) {
                        analyseUrl = activeInstance.getUrl();
                    }
                    reqUrls.add(analyseUrl);
                }
            }

        } else {
            reqUrls.add(url);
        }
        return reqUrls;
    }

    private List<String> analyseVariableUrl(List<String> urls, Map<String, String> variableMap) {
        List<String> reqUrls = new ArrayList<>();
        for (String thisUrl : urls) {
            if (thisUrl.indexOf("${") >= 0) {
                thisUrl = ExtractUrlUtils.replaceVariables(thisUrl, variableMap);
            }
            reqUrls.add(thisUrl);
        }
        return reqUrls;
    }

    private List<String> analyseMultiVariableUrl(List<String> urls, Map<String, String> variableMap) {
        List<String> reqUrls = new ArrayList<>();
        for (String thisUrl : urls) {
            if (thisUrl.indexOf("${{") >= 0) {
                int start = thisUrl.indexOf("${{");
                int end = thisUrl.indexOf("}}");
                String variableKey = thisUrl.substring(start + 3, end);
                Object variableObject = variableMap.get(variableKey);
                String values [] = null;
                if(variableObject instanceof String){
                    String variableValue = variableObject.toString();
                    values = variableValue.split("\n|,");
                }else{
                    values = ((com.alibaba.fastjson.JSONArray)variableObject).toArray(new String[0]);
                }
//                String variableValue = variableMap.get(variableKey);
//                String[] values = variableValue.split("\n|,");
                for (String value : values) {
                    String removeStr = thisUrl.substring(start, end + 2);
                    String newUrl = thisUrl.replace(removeStr, value);
                    if (newUrl.indexOf("${{") >= 0) {
                        reqUrls.addAll(analyseMultiVariableUrl(Arrays.asList(new String[]{newUrl}), variableMap));
                    } else {
                        reqUrls.add(newUrl);
                    }
                }
            } else {
                reqUrls.add(thisUrl);
            }
        }
        return reqUrls;
    }

    private List<String> analyseRangeVariableUrl(List<String> urls) {
        List<String> reqUrls = new ArrayList<>();
        for (String thisUrl : urls) {
            if (thisUrl.indexOf("$[") >= 0) {
                int start = thisUrl.indexOf("$[");
                int end = thisUrl.indexOf("]");
                String regex = thisUrl.substring(start + 2, end);
                String[] split = regex.split("-");
                Integer startNum = Integer.valueOf(split[0]);
                Integer endNum = Integer.valueOf(split[1]);
                for (Integer i = startNum; i <= endNum; i++) {
                    String removeStr = thisUrl.substring(start, end + 2);
                    String newUrl = thisUrl.replace(removeStr, i.toString());
                    reqUrls.add(newUrl);
                }
            } else {
                reqUrls.add(thisUrl);
            }
        }
        return reqUrls;
    }


    @Transactional
    public ClientResultVo startActive(Long activeProcessId, Long prevActiveId, boolean isNext) {
        Active active = this.activeService.findById(prevActiveId);
        if (isNext) {
            ActiveQuery activeQuery = new ActiveQuery();
            activeQuery.setTemplateId(active.getTemplateId());
            activeQuery.setStatus(YesNoEnum.YES.getCode());
            activeQuery.setOrderNo(active.getOrderNo() + 1);
            active = this.activeService.findOne(activeQuery);
        }



        if (active == null) {
            logger.info("activeProcess finished,activeProcessId={}", activeProcessId);
            //完成后，修改状态为成功
            this.success(activeProcessId);
            return null;
        }
        ActiveQuery activeQuery = new ActiveQuery();
        activeQuery.setTemplateId(active.getTemplateId());
        activeQuery.setStatus(YesNoEnum.YES.getCode());
        activeQuery.setOrderNoGt(active.getOrderNo());
        long activeCount = activeService.count(activeQuery);
        Integer hasNextActive = activeCount > 0 ? 1 : 0;

        Long activeId = active.getId();
        logger.info("start active activeProcessId={},prevActiveId={},currentActiveId={}", activeProcessId, prevActiveId, activeId);
        Long templateId = active.getTemplateId();
        Template template = templateService.findById(templateId);
        String variables = template.getVariables();
        Map<String, String> variableMap = JsonUtil.json2Map(variables);

//        List<ActiveInstance> activeInstanceList = new ArrayList<>();
        List<String> reqUrls = analyseUrl(active.getUrl(), activeProcessId, prevActiveId, variableMap);

        //url 去重
        reqUrls = new ArrayList<>(new LinkedHashSet<>(reqUrls));

        int totalNum = reqUrls.size();
        int beforeSampleTotalNum = totalNum;
        //抽样处理
        Integer sampleValue = template.getSampleValue();
        if (template.getSampleType() == SampleTypeEnum.NUMERAL.getCode()) {
            totalNum = NumberUtils.min(sampleValue, totalNum);
        } else {
            BigDecimal divide = BigDecimal.valueOf(totalNum).multiply(BigDecimal.valueOf(sampleValue)).divide(BigDecimal.valueOf(100), RoundingMode.HALF_UP);
            totalNum = divide.intValue();
        }
        reqUrls = reqUrls.subList(0, totalNum);
        logger.info("before sample num={},after num={}", beforeSampleTotalNum, totalNum);


        //主活动实例
        ActiveMainInstance activeMainInstance = new ActiveMainInstance();
        activeMainInstance.setTemplateId(templateId);
        activeMainInstance.setStatus(ProcessStatusEnum.RUNNING.getCode());
        activeMainInstance.setActiveId(activeId);
        activeMainInstance.setName(active.getName());
        activeMainInstance.setActiveProcessId(activeProcessId);
        activeMainInstance.setTotalNum(totalNum);
        activeMainInstance.setSuccessNum(0);
        activeMainInstance.setFailNum(0);
        activeMainInstanceService.save(activeMainInstance);
        Long mainActiveInstanceId = activeMainInstance.getId();

        logger.info("activeName={},get task size={}", active.getName(), reqUrls.size());

        if (StringUtils.equalsAnyIgnoreCase(crawlerModel, "client")) { //如果是客户端模式，直接添加到缓存队列
            //构建客户端任务实例，发送到客户端
            ClientActiveProcessTaskVo clientActiveProcessTaskVo = new ClientActiveProcessTaskVo();
            clientActiveProcessTaskVo.setActiveProcessId(activeProcessId);
            clientActiveProcessTaskVo.setHasNextActive(hasNextActive);
            clientActiveProcessTaskVo.setMethod(active.getMethod());
            clientActiveProcessTaskVo.setRequestType(active.getRequestType());

            String cookie = active.getCookie();
            String requestHeaders = active.getRequestHeaders();
            if (StringUtils.isNoneBlank(cookie)) {
                HashMap<String, String> requestHeaderMap = JsonUtil.json2Map(requestHeaders);
                if(requestHeaderMap == null){
                    requestHeaderMap = new HashMap<>();
                }
                requestHeaderMap.put("cookie",cookie);
                requestHeaders = JsonUtil.map2Json(requestHeaderMap);
            }
            clientActiveProcessTaskVo.setRequestHeaders(requestHeaders);
            clientActiveProcessTaskVo.setRequestBody(active.getRequestBody());   //动态解析 todo
            clientActiveProcessTaskVo.setTemplateId(active.getTemplateId());
            clientActiveProcessTaskVo.setName(template.getName());
            clientActiveProcessTaskVo.setActiveName(active.getName());
            clientActiveProcessTaskVo.setStorePageSource(0);
            clientActiveProcessTaskVo.setTimeRdMs(template.getRunRdMs());
            clientActiveProcessTaskVo.setActiveId(active.getId());
//                clientActiveProcessTaskVo.setActiveInstanceId(0L);
//                clientActiveProcessTaskVo.setActiveId(0L);
//                clientActiveProcessTaskVo.setCookie("");
//                clientActiveProcessTaskVo.setStartTime(0L);
            clientActiveProcessTaskVo.setAnalyseBanExpress(active.getAnalyseBanExpress());
            clientActiveProcessTaskVo.setAnalyseExpress(active.getAnalyseExpress());
            clientActiveProcessTaskVo.setAnalyseDataExpress(active.getAnalyseDataExpress());
//                clientActiveProcessTaskVo.setSwitchProxyExpress("");
            clientActiveProcessTaskVo.setExtractDataUrl(active.getExtractDataUrl());
            clientActiveProcessTaskVo.setSliceActive(active.getSliceActive());
            clientActiveProcessTaskVo.setWaitCssSelectorExpress(active.getWaitCssSelectorExpress());
            clientActiveProcessTaskVo.setDirtyCssSelectorExpress(active.getDirtyCssSelectorExpress());
            clientActiveProcessTaskVo.setUiEventScript(active.getUiEventScript());
            clientActiveProcessTaskVo.setAnalyseExpressType(active.getAnalyseExpressType());
            clientActiveProcessTaskVo.setVariables(template.getVariables());
            clientActiveProcessTaskVo.setRunTimeout(active.getRunTimeout());
            clientActiveProcessTaskVo.setUrls(reqUrls);

            ClientResultVo clientResultVo = new ClientResultVo();
            clientResultVo.setCreateWin(true);
            clientResultVo.setClientActiveProcessTaskVo(clientActiveProcessTaskVo);

            return clientResultVo;

        } else {  //非客户端模式才保存活动实例
            for (String thisUrl : reqUrls) {
                //创建流程活动实例
                ActiveInstance activeInstance = new ActiveInstance();
                activeInstance.setActiveId(activeId);
                activeInstance.setName(active.getName());
                activeInstance.setActiveProcessId(activeProcessId);
                activeInstance.setActiveMainInstanceId(mainActiveInstanceId);
                activeInstance.setTemplateId(templateId);
                activeInstance.setUrl(thisUrl);
                activeInstance.setStatus(ProcessStatusEnum.RUNNING.getCode());
                activeInstance.setTaskStatus(YesNoEnum.NO.getCode());
//            activeInstance.setActive(active);
                activeInstance.setIntercept(true);
                activeInstanceService.save(activeInstance);
//            activeInstanceList.add(activeInstance);

//            if(StringUtils.equalsAnyIgnoreCase(crawlerModel,"client")){ //如果是客户端模式，直接添加到缓存队列
                boolean result = activeInstanceService.addToQueue(activeInstance);
//            }
            }
        }
        return null;

        //添加任务到任务池
//        for (ActiveInstance activeInstance : activeInstanceList) {
//            TaskMessage<Long> taskMessage = new TaskMessage<>();
//            taskMessage.setData(activeInstance.getId());
//            taskMessage.setReqType(RequestTypeEnum.getByCode(activeInstance.getActive().getRequestType()).getValue());
//            taskMessage.setSpeed(TaskSpeedEnum.SLOW.getCode());
//            taskMessageHandler.addTaskMessage(taskMessage);
//        }


    }

    public void success(Long activeProcessId) {
        ActiveProcess activeProcess = this.findById(activeProcessId);
        activeProcess.setStatus(YesNoEnum.YES.getCode());
        this.save(activeProcess);

        //修改模版状态
        templateService.updateStatus(activeProcess.getTemplateId(), TemplateStatusEnum.FINISHED.getCode());

        //删除缓存队列(不要清除，因为类型cache必须要存在)
//        ActiveQuery activeQuery = new ActiveQuery();
//        activeQuery.setTemplateId(activeProcess.getTemplateId());
//        List<ActiveVo> activeList = activeService.findVoAll(activeQuery);
//        for (ActiveVo activeVo : activeList) {
//            redisTemplate.opsForHash().delete(CrawlerCacheConstants.CRAWLER_TASK_TYPE, activeVo.getId().toString());
////            String queueKey = CrawlerCacheConstants.CRAWLER_TASK_QUEUE +"_"+activeVo.getId();
////            redisTemplate.delete(queueKey);
//        }
    }


    private void setTaskCache(ActiveProcess activeProcess) {
        Template template = templateService.findById(activeProcess.getTemplateId());
        String runRdMs = template.getRunRdMs();
        Long waitTime = Long.valueOf(runRdMs.split("-")[0]);

        //创建任务缓存
        String name = activeProcess.getName();
        TaskTypeVo taskTypeVo = new TaskTypeVo();
        taskTypeVo.setName(name);
        taskTypeVo.setWaitTime(waitTime);
        taskTypeVo.setTaskId(activeProcess.getId());
        taskTypeVo.setLastTime(System.currentTimeMillis());
//        taskTypeVo.setStatus(YesNoEnum.YES.getCode());

        redisTemplate.opsForHash().putIfAbsent(CrawlerCacheConstants.CRAWLER_TASK_TYPE, activeProcess.getId().toString(), taskTypeVo);

    }


    @Transactional
    public ClientResultVo start(Long templateId) {
        //获取模板
        Template template = this.templateService.findById(templateId);

        //获得第一个活动
        ActiveQuery activeQuery = new ActiveQuery();
        activeQuery.setTemplateId(templateId);
        activeQuery.setStatus(YesNoEnum.YES.getCode());
        activeQuery.setOrderNo(1);
        Active active = this.activeService.findOne(activeQuery);
        if (active == null) {
            throw new BizException("暂无活动");
        }
        //创建流程实例
        ActiveProcess activeProcess = new ActiveProcess();
        activeProcess.setName(template.getName());
        activeProcess.setTemplateId(templateId);
        activeProcess.setStatus(ProcessStatusEnum.RUNNING.getCode());
        activeProcess.setVariables(template.getVariables());  //暂时直接替换，后续会产生中间变量 todo
        this.save(activeProcess);
        setTaskCache(activeProcess);

        //修改模版状态
        templateService.updateStatus(template.getId(), TemplateStatusEnum.RUNNING.getCode());

        ClientResultVo clientResultVo = this.startActive(activeProcess.getId(), active.getId(), false);
        return clientResultVo;
    }


    public void updateStatus(Long activeProcessId, Integer status) {
        //修改类型任务状态
        if (status == ProcessStatusEnum.PAUSED.getCode() || status == ProcessStatusEnum.RUNNING.getCode()) {
            TaskTypeVo taskTypeVo = (TaskTypeVo) redisTemplate.opsForHash().get(CrawlerCacheConstants.CRAWLER_TASK_TYPE, activeProcessId.toString());
            if (status == ProcessStatusEnum.PAUSED.getCode()) {
                taskTypeVo.setStatus(YesNoEnum.NO.getCode());
            } else {
                taskTypeVo.setStatus(YesNoEnum.YES.getCode());
            }
            redisTemplate.opsForHash().put(CrawlerCacheConstants.CRAWLER_TASK_TYPE, activeProcessId.toString(), taskTypeVo);
        }
        this.getBaseMapper().updateStatus(activeProcessId, status);

    }

    /**
     * 暂停
     *
     * @param activeProcessId
     */
    @Transactional
    public void pause(Long activeProcessId) {

//        //获取改活动下，正在进行的活动实例
//        ActiveMainInstanceQuery activeMainInstanceQuery = new ActiveMainInstanceQuery();
//        activeMainInstanceQuery.setActiveProcessId(activeProcessId);
//        activeMainInstanceQuery.setStatus(YesNoEnum.NO.getCode());
//        ActiveMainInstance activeMainInstance = activeMainInstanceService.findOne(activeMainInstanceQuery);
//        if(activeMainInstance != null){
//            activeService.updateStatus(activeMainInstance.getActiveId(),YesNoEnum.NO.getCode());  //设置不可用，任务队列暂时阻塞
//        }

        ActiveProcess activeProcess = this.findById(activeProcessId);

        updateStatus(activeProcessId, ProcessStatusEnum.PAUSED.getCode());

        //修改模版状态
        templateService.updateStatus(activeProcess.getTemplateId(), TemplateStatusEnum.PAUSED.getCode());



    }

    /**
     * 恢复
     *
     * @param activeProcessId
     */
    @Transactional
    public void resume(Long activeProcessId) {
//        //获取改活动下，正在进行的活动实例
//        ActiveMainInstanceQuery activeMainInstanceQuery = new ActiveMainInstanceQuery();
//        activeMainInstanceQuery.setActiveProcessId(activeProcessId);
//        activeMainInstanceQuery.setStatus(YesNoEnum.NO.getCode());
//        ActiveMainInstance activeMainInstance = activeMainInstanceService.findOne(activeMainInstanceQuery);
//        if(activeMainInstance != null){
//            activeService.updateStatus(activeMainInstance.getActiveId(),YesNoEnum.YES.getCode());  //设置开启
//        }

        ActiveProcess activeProcess = this.findById(activeProcessId);

        updateStatus(activeProcessId, ProcessStatusEnum.RUNNING.getCode());

        //修改模版状态
        templateService.updateStatus(activeProcess.getTemplateId(), TemplateStatusEnum.RUNNING.getCode());
//
//        if (StringUtils.equalsAnyIgnoreCase(crawlerModel, "client")) {
//            //给客户端发消息
//            RequestRes requestRes = new RequestRes();
//            requestRes.setMethod("POST");
////                requestRes.setHeaders(headerMap);
//            requestRes.setUrl(crawlerUrl + "updateProcessStatus");
//            requestRes.setParamText("{\"activeProcessId\":" + activeProcessId + ",\"status\":1}");
////            requestRes.setParamText(JsonUtil.bean2Json(clientActiveProcessTaskVo));
//            ResponseRes responseRes = HttpNewUtils.execute(requestRes);
//            logger.info("http updateProcessStatus  finished!activeProcessId={}, responseRes={}", activeProcessId, responseRes);
//        }
    }

    /**
     * 结束
     *
     * @param activeProcessId
     */
    @Transactional
    public void close(Long activeProcessId) {
        ActiveProcess activeProcess = this.findById(activeProcessId);

        String queueKey = CrawlerCacheConstants.CRAWLER_TASK_QUEUE + "_" + activeProcessId;
        redisTemplate.delete(queueKey);

        updateStatus(activeProcessId, ProcessStatusEnum.CLOSE.getCode());

        //修改模版状态
        templateService.updateStatus(activeProcess.getTemplateId(), TemplateStatusEnum.FINISHED.getCode());

//        if (StringUtils.equalsAnyIgnoreCase(crawlerModel, "client")) {
//            //给客户端发消息
//            RequestRes requestRes = new RequestRes();
//            requestRes.setMethod("POST");
////                requestRes.setHeaders(headerMap);
//            requestRes.setUrl(crawlerUrl + "updateProcessStatus");
//            requestRes.setParamText("{\"activeProcessId\":" + activeProcessId + ",\"status\":0}");
////            requestRes.setParamText(JsonUtil.bean2Json(clientActiveProcessTaskVo));
//            ResponseRes responseRes = HttpNewUtils.execute(requestRes);
//            logger.info("http updateProcessStatus  finished!activeProcessId={}, responseRes={}", activeProcessId, responseRes);
//        }

    }

    public void setAtoIntercept(boolean status) {
        atoIntercept.set(status);
        dataConfigService.updateValueByCode(CrawlerConstants.ACTIVE_TASK_INTERCEPT, "" + status);
    }

    public void checkIntercept(Long activeInstanceId) {
        try {
            if (atoIntercept.get()) {
                while (true) {
                    if (!atoIntercept.get()) {
                        break;
                    }
                    //单个活动已跳过
                    ActiveInstance activeInstance = activeInstanceService.findById(activeInstanceId);
                    if (!activeInstance.getIntercept()) {
                        break;
                    }
                    Thread.sleep(1000);
                }
            }
        } catch (Exception e) {
            logger.error("error", e);
        }
    }


    /**
     * 从异常中开始(服务宕机，程序异常挂掉)
     *
     * @param activeProcessId
     */
    @Transactional
    public void restart(Long activeProcessId) {
        ActiveProcess activeProcess = this.findById(activeProcessId);
        if (activeProcess.getStatus() == YesNoEnum.YES.getCode()) {
            throw new BizException("该流程实例已结束");
        }
        //找到最后一个未完成的活动
        ActiveInstanceQuery activeInstanceQuery = new ActiveInstanceQuery();
        activeInstanceQuery.setActiveProcessId(activeProcessId);
        activeInstanceQuery.setStatusList(Arrays.asList(new Integer[]{ProcessStatusEnum.RUNNING.getCode()}));
        List<ActiveInstance> activeInstanceList = this.activeInstanceService.findAll(activeInstanceQuery);
//        logger.info("get not finished activeProcess Name={}, activeInstance size={}",activeProcess.getName(),activeInstanceList.size());

        if (CollectionUtils.isEmpty(activeInstanceList)) {
            //如果没有未完成的，获取已完成最后一条，重新处理
            activeInstanceQuery = new ActiveInstanceQuery();
            activeInstanceQuery.setActiveProcessId(activeProcessId);
            activeInstanceQuery.setStatus(YesNoEnum.YES.getCode());
            activeInstanceQuery.setResultLimit(1);
            ActiveInstance activeInstance = this.activeInstanceService.findOne(activeInstanceQuery);
            activeInstance.setStatus(YesNoEnum.NO.getCode());
            activeInstance.setTaskStatus(YesNoEnum.NO.getCode());
            activeInstanceService.save(activeInstance);
            activeInstanceList.add(activeInstance);

            //主活动实例成功数-1
            activeMainInstanceService.decrSuccessNum(activeInstance.getActiveMainInstanceId(), 1);
            activeMainInstanceService.updateToFail(activeInstance.getActiveMainInstanceId());
        }
        for (ActiveInstance activeInstance : activeInstanceList) {
            activeInstance.setTaskStatus(YesNoEnum.NO.getCode());
            activeInstanceService.save(activeInstance);
        }
        logger.info("get not finished activeProcess Name={}, activeInstance size={}", activeProcess.getName(), activeInstanceList.size());

    }

    @Transactional
    public int runningTaskClear(Long activeProcessId) {
        //获取当前主活动下[运行中]的活动实例列表
        ActiveMainInstanceQuery activeMainInstanceQuery = new ActiveMainInstanceQuery();
        activeMainInstanceQuery.setActiveProcessId(activeProcessId);
        activeMainInstanceQuery.setStatus(YesNoEnum.NO.getCode());
        ActiveMainInstance activeMainInstance = activeMainInstanceService.findOne(activeMainInstanceQuery);
        if (activeMainInstance == null) {
            logger.warn("no activeMainInstance");
            return 0;
        }
        ActiveInstanceQuery activeInstanceQuery = new ActiveInstanceQuery();
        activeInstanceQuery.setActiveProcessId(activeProcessId);
        activeInstanceQuery.setActiveMainInstanceId(activeMainInstance.getId());
        activeInstanceQuery.setTaskStatus(YesNoEnum.YES.getCode());

        List<Integer> statusList = new ArrayList<>();
        statusList.add(ActiveInstanceStatusEnum.RUNNING.getCode());
        activeInstanceQuery.setStatusList(statusList);
        List<ActiveInstance> activeInstanceList = this.activeInstanceService.findAll(activeInstanceQuery);
        int clearQueueSize = 0;
        for (ActiveInstance activeInstance : activeInstanceList) {
            int result = activeInstanceService.updateTaskStatusAndStatus(activeInstance.getId(), YesNoEnum.NO.getCode(), ActiveInstanceStatusEnum.FAILED.getCode());
            if (result > 0) {
                clearQueueSize++;
//                activeInstance.setResponseAnalyseBody("");
//                activeInstance.setResponseBody("");
//                activeInstance.setResponseRawHeader("");
                //重新设置进入，不然那后面保存会覆盖
                activeInstance.setStatus(ActiveInstanceStatusEnum.FAILED.getCode());
                activeInstance.setTaskStatus(YesNoEnum.NO.getCode());
                activeInstance.setErrContent("手动失败");
                this.activeInstanceService.save(activeInstance);
            } else {
                logger.warn("handle RUNNING task clear failed,activeInstanceId={}", activeInstance.getId());
            }
        }
        return clearQueueSize;
    }

    @Transactional
    public int retrieveTaskToQueue(Long activeProcessId) {
        //获取当前主活动下[初始化，失败]的活动实例列表
        ActiveMainInstanceQuery activeMainInstanceQuery = new ActiveMainInstanceQuery();
        activeMainInstanceQuery.setActiveProcessId(activeProcessId);
        activeMainInstanceQuery.setStatus(YesNoEnum.NO.getCode());
        ActiveMainInstance activeMainInstance = activeMainInstanceService.findOne(activeMainInstanceQuery);
        if (activeMainInstance == null) {
            logger.warn("no activeMainInstance");
            return 0;
        }
        ActiveInstanceQuery activeInstanceQuery = new ActiveInstanceQuery();
        activeInstanceQuery.setActiveProcessId(activeProcessId);
        activeInstanceQuery.setActiveMainInstanceId(activeMainInstance.getId());
        activeInstanceQuery.setTaskStatus(YesNoEnum.NO.getCode());

        List<Integer> statusList = new ArrayList<>();
        statusList.add(ActiveInstanceStatusEnum.INIT.getCode());
        statusList.add(ActiveInstanceStatusEnum.FAILED.getCode());
        activeInstanceQuery.setStatusList(statusList);
        List<ActiveInstance> activeInstanceList = this.activeInstanceService.findAll(activeInstanceQuery);
//        logger.info("retrieveTaskToQueue activeInstance size={}",activeInstanceList.size());

        //设置task状态
        int addQueueSize = 0;
        for (ActiveInstance activeInstance : activeInstanceList) {
            boolean result = activeInstanceService.addToQueue(activeInstance);
            if (result) {
                addQueueSize++;
            }
        }
        logger.info("retrieveTaskToQueue activeInstance size={}", addQueueSize);
        return addQueueSize;

    }


}
